import {
  ApiConsumes,
  ApiOperation,
  ApiResponse,
  ApiTags,
} from '@nestjs/swagger';
import {
  Controller,
  Body,
  Get,
  Post,
  HttpStatus,
  Query,
  Delete,
  BadRequestException,
} from '@nestjs/common';
import { spawn } from 'child_process';
import { BackupDto, systemDto, dBackupDto } from './../dtos/backup.dto';
import * as moment from 'moment';
import { successfulDto } from '../dtos/successful.dto';
import { errorDto } from '../dtos/error.dto';
import { SwaggerBaseApiResponse } from '../dtos/base-api-response.dto';
import { metaDto } from '../dtos/meta.dto';

@ApiTags('系统维护')
@Controller('system')
export class SystemController {
  constructor() {}

  @ApiOperation({
    summary: '数据库备份列表',
  })
  @ApiResponse({
    status: HttpStatus.OK,
    type: SwaggerBaseApiResponse('systemDtoAll', systemDto, metaDto),
  })
  @ApiResponse({
    status: HttpStatus.BAD_REQUEST,
    type: errorDto,
  })
  @Get('/database')
  async list() {
    //docker-compose exec -T mongo ls /dump
    const ret = await this.spawn(
      'docker-compose',
      ['exec', '-T', 'mongo', 'ls', '/dump'],
      { cwd: './' },
    );
    const data = ('' + ret).split('\n');
    data.pop();
    return {
      data,
      meta: {
        total: data.length,
      },
    };
  }
  @ApiOperation({
    summary: '数据库备份',
  })
  @Post('/database/dump')
  @ApiResponse({
    status: HttpStatus.OK,
    type: successfulDto,
  })
  @ApiResponse({
    status: HttpStatus.BAD_REQUEST,
    type: errorDto,
  })
  async dump(@Body() data) {
    const ret = await this.spawn(
      'docker-compose',
      [
        'exec',
        '-T',
        'mongo',
        'mongodump',
        '--db',
        'backend-template-service',
        '--out',
        '/dump/' + moment().format('YYYYMMDDhhmmss'),
      ],
      { cwd: './' },
    );
    return {
      statusCode: 200,
      message: '数据库备份成功',
    };
  }
  @ApiOperation({
    summary: '数据库恢复',
  })
  @Post('/database/restore')
  @ApiResponse({
    status: HttpStatus.OK,
    type: successfulDto,
  })
  @ApiResponse({
    status: HttpStatus.BAD_REQUEST,
    type: errorDto,
  })
  @ApiConsumes('multipart/form-data')
  async restore(@Query() dto: BackupDto) {
    console.log('恢复数据', dto.file);
    const ret = await this.spawn(
      'docker-compose',
      [
        'exec',
        '-T',
        'mongo',
        'mongorestore',
        '--db',
        'backend-template-service',
        `/dump/${dto.file}/backend-template-service`,
      ],
      { cwd: './' },
    );

    return {
      statusCode: 200,
      message: '数据恢复成功',
    };
  }

  @ApiOperation({
    summary: '删除数据库备份列表',
  })
  @ApiResponse({
    status: HttpStatus.OK,
    type: successfulDto,
  })
  @ApiResponse({
    status: HttpStatus.BAD_REQUEST,
    type: errorDto,
  })
  @Delete('/database/delete')
  @ApiConsumes('multipart/form-data')
  async remove(@Query() dto: dBackupDto) {
    if (dto.file == 'init') {
      throw new BadRequestException('init 不能删除');
    }
    if (dto.file == '重点保护对象') {
      throw new BadRequestException('重点保护对象 不能删除');
    }
    const ret = await this.spawn(
      'docker-compose',
      ['exec', '-T', 'mongo', 'rm', '-r', `/dump/${dto.file}`],
      { cwd: './' },
    );
    console.log('1111', ret);
    return {
      statusCode: 200,
      message: '删除成功',
    };
  }
  async spawn(cmd, ...args) {
    return new Promise((res, reject) => {
      const child = spawn(cmd, ...args);
      // 日志流的对接
      child.stdout.pipe(process.stdout); //终端正常流
      child.stderr.pipe(process.stderr); //终端异常流
      let ret = '';
      let errMsg = '';
      //当有错误输出时，将错误信息打印到控制台
      child.stdout.on('data', (data) => {
        console.log('data', data);
        ret += data.toString();
      });
      // 当有错误输出时，将错误信息打印到控制台
      child.stderr.on('data', (data) => {
        console.error(`stderr: ${data}`);
        errMsg = data;
      });
      //当子进程退出时，输出退出码
      child.on('close', (code) => {
        console.log('close', code, ret);
        if (code == 1) {
          console.log('errMsg', `${errMsg}`);
          reject(errMsg);
        }
        res(ret);
      });
    });
  }
  getTime() {
    //转毫秒
    const n = new Date();
    console.log(n);
    return (
      n.getFullYear() +
      (n.getMonth() + 1) +
      n.getDate() +
      n.getHours() +
      n.getMinutes() +
      n.getSeconds()
    );
  }
}
